#! /usr/bin/env python
"""config helpers

Copyright (C) 2011-2013 Christian T. Steigies <steigies@physik.uni-kiel.de>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
"""

__author__ = "Christian T. Steigies <steigies@physik.uni-kiel.de>"
__license__ = "GPL License"


import os
import sys
import optparse  # http://wiki.python.org/moin/OptParse
import ConfigParser  # http://wiki.python.org/moin/ConfigParserExamples
import datetime

from nmdb.tools.datetool import str2datetime

## --------------------------------------------------------------------------
def parse_options(mode="unconfigured"):
    """parse command line options"""
    # TODO: store mode?
    # TODO: write mode -> upload mode
    
    if mode in ["sqlite"]:
        parser = optparse.OptionParser("usage: %prog [options] [station] [1m|1h]")
        parser.add_option("-Y", "--year", dest="year", default=None,
                      type="int", help="convert data for this year")
        parser.add_option("-M", "--month", dest="month", default=None,
                      type="int", help="convert data for this month (and year)")
        parser.add_option("-0", "--nullok", action="store_true", dest="nullok",
                          default=False, help="also store all NULL values in sqlite file")

    else:
        parser = optparse.OptionParser("usage: %prog [options] [station] [ori|rev|1h|env|meta]")
        
    parser.add_option("-f", "--file", dest="rcfile",
                      default=os.environ["HOME"] + "/.nmdbrc",
                      type="string", help="config file for NMDB")

    parser.add_option("-v", dest="verbose", default=0, action="count",
            help="increment output verbosity; may be specified multiple times")
 
    if mode in ["unconfigured"]:
        raise ValueError  # parse_options: mode is not set
        
    if mode in ["upload", "revise", "write"]:
        parser.add_option("-H", "--host", dest="hostname",
                          default="db01.nmdb.eu", type="string",
                          help="specify hostname to run on")
    elif mode in ["read"]:
        parser.add_option("-H", "--host", dest="hostname",
                          default="db03.nmdb.eu", type="string",
                          help="specify hostname to run on")
    else:
        parser.add_option("-H", "--host", dest="hostname",
                          default="db04.nmdb.eu", type="string",
                          help="specify hostname to run on")

    parser.add_option("-P", "--port", dest="portnum", default=3306,
                      type="int", help="port number to run on")

    parser.add_option("-n", "--dry-run", action="store_true", dest="dryrun",
                      default=False,
                      help="print the commands that would be executed, but do not execute them")

    parser.add_option("-D", "--datadir", dest="datadir",
                      default="/var/tmp/nmdb", type="string",
                      help="specify data directory for temporary files")

    if mode in ["upload", "write"]:  # limit writing of real-time data
        parser.add_option("-m", "--max", dest="maxcount", default=120, type="int",
                          help="max number of datapoints to send")
        parser.add_option("-T", "--timeout", dest="timeout", default=30, type="int",
                          help="Stop sending after timeout seconds.")
    elif mode in ["revise"]:  # write unlimited revised data
        parser.add_option("-m", "--max", dest="maxcount", default=-1, type="int",
                          help="max number of datapoints to send")
    elif mode in ["read"]:
        parser.add_option("-s", "--show", action="store_true", dest="show",
                          default=False, help="only show the last datapoint")
        parser.add_option("-c", "--count", dest="tcount", type="string",
                          help="count data for \"yyyy-mm-dd HH:MM:SS\" day in specified table")

    if mode in ["read", "upload", "revise", "write"]:
        parser.add_option("-t", "--startdatetime", dest="tstart",
                          default="1900-01-01 00:00:00", type="string",
                          help="start datetime \"yyyy-mm-dd HH:MM:SS\" to use when updating data")
        parser.add_option("-p", "--stopdatetime", dest="tstopp",
                          type="string",
                          help="stop datetime \"yyyy-mm-dd HH:MM:SS\" to use when updating data")

    (options, args) = parser.parse_args()

    return (options, args)


## --------------------------------------------------------------------------
def config_section_map(section, config):
    """return configuration as dict"""

    dict1 = {}
    options = config.options(section)
    for option in options:
        try:
            dict1[option] = config.get(section, option)
            if dict1[option] == -1:
                #DebugPrint("skip: %s" % option)
                pass
        except:
            print("exception on %s!" % option)
            dict1[option] = None
    return dict1


## --------------------------------------------------------------------------
def parse_config(rcfile, station, mode="nmdb"):
    """
    get username and password from .nmdbrc file
    (instead of storing them in the code)
    """

    config = ConfigParser.ConfigParser()
    try:
        config.read(rcfile)
    except:
        print "parse_config: rcfile not found:", rcfile
        sys.exit(0)

    try:
    # credentials for nmdadb data is stored in nmdbrc as kiel2_nmdadb station
        if mode == "nmdadb":
            station = station + "_" + mode
    # credentials for calgary old data is stored in nmdbrc as calg_data station
        elif mode == "calg_old":
            station = station + "_" + "data"

        username = config_section_map(station, config)['username']
        password = config_section_map(station, config)['password']

        # nmdadb mode stores information on MySQL server, options are used only for NMDB server
        if mode in ["nmdadb", "calg_old"]:
            hostname = config_section_map(station, config)['hostname']
            dbname = config_section_map(station, config)['dbname']
            portnumber = config_section_map(station, config)['port']
            return(username, password, hostname, dbname, int(portnumber))

        # orc: Mexico PostgreSQL database
        if mode == "orc":
            hostname = config_section_map(station, config)['hostname']
            return(username, password, hostname)

        # perhaps change this to "download" mode?
        if mode in ["download"] or station == "download":
            longname = "download"
        else:
            longname = config_section_map(station, config)['longname']

        return(username, password, longname)

    except ConfigParser.NoSectionError:
        print "config for station %s not found in %s" % (station, rcfile)
        sys.exit(0)


## --------------------------------------------------------------------------
def parse_args(options, args, mode="write"):
    """
    parse commandline arguments
    valid modes:
        write: write to NMDB
        read: read from NMDB
        sql: write to sqlite file (station2sql)
    """

    # determine station name
    if len(args) > 0:
        station = args[0]
    else:
        raise ValueError  # no station given

    # determine NMDB table to be used
    # default: ori, rev is the same as ori
    if len(args) > 1:
        table = args[1]
        if table == "rev":
            table = "ori"
    else:
        table = "ori"

    if mode == "write":
        if table in ["1m", "ori", "rev"]:
            # minute data: up to one year of data
            if options.maxcount < 0:
                options.maxcount = 60 * 24 * 366
           
        elif table in ["1h"]:
            # hour data: up to one year of data
            if options.maxcount < 0:
                options.maxcount = 24 * 366

        elif table in ["env", "meta"]:
            print table, ": not yet implemented"
            raise ValueError

        else:
            print "invalid table selected: ", table
            raise ValueError

    elif mode == "read":
        if table in ["1m", "ori", "1h"]:
            pass
        elif table in ["env", "meta"]:
            pass

    elif mode == "sql":
        pass

    else:
        raise ValueError  # invalid mode

    if len(args) > 2:
        print "extra args not yet supported", args[2:]
        sys.exit(1)

    if options.verbose > 1:
        print "parse_args:", station, table

    return(station, table)


## --------------------------------------------------------------------------
def date_range(data, options):
    """
    determine date range for data to be sent
    get start and stopp data from data
    can be overridden with -t TSTART and -p TSTOPP options
    """
    start_date = data.min()
    stopp_date = data.max()
    try:
        start_opts = str2datetime(options.tstart)
    except ValueError:
        start_opts = start_date
    try:
        stopp_opts = str2datetime(options.tstopp)
    except ValueError:
        stopp_opts = stopp_date

    if start_opts > start_date:
        if start_opts > stopp_date:
            if options.verbose > 1:
                print "tstart larger then end of file"
        else:
            if options.verbose > 1:
                print "using tstart"
            start_date = start_opts
    if stopp_opts < stopp_date :
        if stopp_opts < start_date:
            if options.verbose > 1:
                print "tstopp smaller then beginning of file"
        else:
            if options.verbose > 1:
                print "using tstopp"
            stopp_date = stopp_opts

    return (start_date, stopp_date)


## --------------------------------------------------------------------------
def main():
    """usage:
    python tools/configtool.py -v -f nmdbrc mcmu
    """
    print "This is the tools.configtool module."

    (myoptions, myargs) = parse_options()
    print "options:", myoptions
    print "args:", myargs
    myrcfile = myoptions.rcfile

    mystation = myargs[0]
    (myusername, mypassword, mylongname) = parse_config(myrcfile, mystation)
    print myusername
    print mypassword
    print mylongname

    
## --------------------------------------------------------------------------
if __name__ == "__main__":
    main()
